namespace javax.sound.sampled
{
	/// <summary>
	/// The <code>LineEvent</code> class encapsulates information that a line
	/// sends its listeners whenever the line opens, closes, starts, or stops.
	/// </summary>
	/// <remarks>
	/// The <code>LineEvent</code> class encapsulates information that a line
	/// sends its listeners whenever the line opens, closes, starts, or stops.
	/// Each of these four state changes is represented by a corresponding
	/// type of event.  A listener receives the event as a parameter to its
	/// <see cref="LineListener.update(LineEvent)">update</see>
	/// method.  By querying the event,
	/// the listener can learn the type of event, the line responsible for
	/// the event, and how much data the line had processed when the event occurred.
	/// <p>Although this class implements Serializable, attempts to
	/// serialize a <code>LineEvent</code> object will fail.
	/// </remarks>
	/// <author>Kara Kytle</author>
	/// <version>1.27, 05/11/17</version>
	/// <seealso cref="Line">Line</seealso>
	/// <seealso cref="LineListener.update(LineEvent)">LineListener.update(LineEvent)</seealso>
	/// <since>1.3</since>
	/// <serial>exclude</serial>
	public class LineEvent : java.util.EventObject
	{
        /// <summary>
		/// The kind of line event (<code>OPEN</code>, <code>CLOSE</code>,
		/// <code>START</code>, or <code>STOP</code>).
		/// </summary>
		/// <remarks>
		/// The kind of line event (<code>OPEN</code>, <code>CLOSE</code>,
		/// <code>START</code>, or <code>STOP</code>).
		/// </remarks>
		/// <seealso cref="getType()">getType()</seealso>
		/// <serial></serial>
		private readonly LineEvent.Type type;

		/// <summary>The media position when the event occurred, expressed in sample frames.</summary>
		/// <remarks>
		/// The media position when the event occurred, expressed in sample frames.
		/// Note that this field is only relevant to certain events generated by
		/// data lines, such as <code>START</code> and <code>STOP</code>.  For
		/// events generated by lines that do not count sample frames, and for any
		/// other events for which this value is not known, the position value
		/// should be
		/// <see cref="AudioSystem.NOT_SPECIFIED">AudioSystem.NOT_SPECIFIED</see>
		/// .
		/// </remarks>
		/// <serial></serial>
		/// <seealso cref="getFramePosition()">getFramePosition()</seealso>
		private readonly long position;

		/// <summary>Constructs a new event of the specified type, originating from the specified line.
		/// 	</summary>
		/// <remarks>Constructs a new event of the specified type, originating from the specified line.
		/// 	</remarks>
		/// <param name="line">the source of this event</param>
		/// <param name="type">the event type (<code>OPEN</code>, <code>CLOSE</code>, <code>START</code>, or <code>STOP</code>)
		/// 	</param>
		/// <param name="position">
		/// the number of sample frames that the line had already processed when the event occurred,
		/// or
		/// <see cref="AudioSystem.NOT_SPECIFIED">AudioSystem.NOT_SPECIFIED</see>
		/// </param>
		/// <exception cref="System.ArgumentException">
		/// if <code>line</code> is
		/// <code>null</code>.
		/// </exception>
		public LineEvent(Line line, LineEvent.Type type, long position)
			 : base(line)
		{
			// INSTANCE VARIABLES
			this.type = type;
			this.position = position;
		}

		/// <summary>Obtains the audio line that is the source of this event.</summary>
		/// <remarks>Obtains the audio line that is the source of this event.</remarks>
		/// <returns>the line responsible for this event</returns>
		public Line getLine()
		{
			return (Line)getSource();
		}

		/// <summary>Obtains the event's type.</summary>
		/// <remarks>Obtains the event's type.</remarks>
		/// <returns>
		/// this event's type (
		/// <see cref="Type.OPEN">Type.OPEN</see>
		/// ,
		/// <see cref="Type.CLOSE">Type.CLOSE</see>
		/// ,
		/// <see cref="Type.START">Type.START</see>
		/// , or
		/// <see cref="Type.STOP">Type.STOP</see>
		/// )
		/// </returns>
		public LineEvent.Type getType()
		{
			return type;
		}

		/// <summary>Obtains the position in the line's audio data when the event occurred, expressed in sample frames.
		/// 	</summary>
		/// <remarks>
		/// Obtains the position in the line's audio data when the event occurred, expressed in sample frames.
		/// For example, if a source line had already played back 14 sample frames at the time it was
		/// paused, the pause event would report the line's position as 14.  The next frame to be processed
		/// would be frame number 14 using zero-based numbering, or 15 using one-based numbering.
		/// <p>
		/// Note that this field is relevant only to certain events generated by
		/// data lines, such as <code>START</code> and <code>STOP</code>.  For
		/// events generated by lines that do not count sample frames, and for any
		/// other events for which this value is not known, the position value
		/// should be
		/// <see cref="AudioSystem.NOT_SPECIFIED">AudioSystem.NOT_SPECIFIED</see>
		/// .
		/// </remarks>
		/// <returns>the line's position as a sample frame number</returns>
		public long getFramePosition()
		{
			return position;
		}

		/// <summary>Obtains a string representation of the event.</summary>
		/// <remarks>
		/// Obtains a string representation of the event.  The contents of the string may vary
		/// between implementations of Java Sound.
		/// </remarks>
		/// <returns>a string describing the event.</returns>
		public override string ToString()
		{
			string sType = string.Empty;
			if (type != null)
			{
				sType = type.ToString() + " ";
			}
			string sLine;
			if (getLine() == null)
			{
				sLine = "null";
			}
			else
			{
				sLine = getLine().ToString();
			}
			return sType + "event from line " + sLine;
		}

		/// <summary>The LineEvent.Type inner class identifies what kind of event occurred on a line.
		/// 	</summary>
		/// <remarks>
		/// The LineEvent.Type inner class identifies what kind of event occurred on a line.
		/// Static instances are provided for the common types (OPEN, CLOSE, START, and STOP).
		/// </remarks>
		/// <seealso cref="LineEvent.getType()">LineEvent.getType()</seealso>
		public class Type
		{
			/// <summary>Type name.</summary>
			/// <remarks>Type name.</remarks>
			private string name;

			/// <summary>Constructs a new event type.</summary>
			/// <remarks>Constructs a new event type.</remarks>
			/// <param name="name">name of the type</param>
			protected Type(string name)
			{
				// $$kk: 03.25.99: why can't this be final??
				this.name = name;
			}

			//$$fb 2002-11-26: fix for 4695001: SPEC: description of equals() method contains typo
			/// <summary>
			/// Indicates whether the specified object is equal to this event type,
			/// returning <code>true</code> if the objects are identical.
			/// </summary>
			/// <remarks>
			/// Indicates whether the specified object is equal to this event type,
			/// returning <code>true</code> if the objects are identical.
			/// </remarks>
			/// <param name="obj">the reference object with which to compare</param>
			/// <returns>
			/// <code>true</code> if this event type is the same as
			/// <code>obj</code>; <code>false</code> otherwise
			/// </returns>
			public sealed override bool Equals(object obj)
			{
				return base.Equals(obj);
			}

			/// <summary>Finalizes the hashcode method.</summary>
			/// <remarks>Finalizes the hashcode method.</remarks>
			public sealed override int GetHashCode()
			{
				return base.GetHashCode();
			}

			/// <summary>Returns the type name as the string representation.</summary>
			/// <remarks>Returns the type name as the string representation.</remarks>
			public override string ToString()
			{
				return name;
			}

			/// <summary>
			/// A type of event that is sent when a line opens, reserving system
			/// resources for itself.
			/// </summary>
			/// <remarks>
			/// A type of event that is sent when a line opens, reserving system
			/// resources for itself.
			/// </remarks>
			/// <seealso cref="CLOSE">CLOSE</seealso>
			/// <seealso cref="Line.open()">Line.open()</seealso>
			public static readonly LineEvent.Type OPEN = new LineEvent.Type
				("Open");

			/// <summary>
			/// A type of event that is sent when a line closes, freeing the system
			/// resources it had obtained when it was opened.
			/// </summary>
			/// <remarks>
			/// A type of event that is sent when a line closes, freeing the system
			/// resources it had obtained when it was opened.
			/// </remarks>
			/// <seealso cref="OPEN">OPEN</seealso>
			/// <seealso cref="Line.close()">Line.close()</seealso>
			public static readonly LineEvent.Type CLOSE = new LineEvent.Type
				("Close");

			/// <summary>
			/// A type of event that is sent when a line begins to engage in active
			/// input or output of audio data in response to a
			/// <see cref="DataLine.start()">start</see>
			/// request.
			/// </summary>
			/// <seealso cref="STOP">STOP</seealso>
			/// <seealso cref="DataLine.start()">DataLine.start()</seealso>
			public static readonly LineEvent.Type START = new LineEvent.Type
				("Start");

			/// <summary>
			/// A type of event that is sent when a line ceases active input or output
			/// of audio data in response to a
			/// <see cref="DataLine.stop()">stop</see>
			/// request,
			/// or because the end of media has been reached.
			/// </summary>
			/// <seealso cref="START">START</seealso>
			/// <seealso cref="DataLine.stop()">DataLine.stop()</seealso>
			public static readonly LineEvent.Type STOP = new LineEvent.Type
				("Stop");
			// LINE EVENT TYPE DEFINES
			//public static final Type EOM	= new Type("EOM");
			//public static final Type ACTIVE	= new Type("ACTIVE");
			//public static final Type INACTIVE	= new Type("INACTIVE");
		}
		// class Type
	}
}
